在剛接觸 Laravel 的 Queue 系統時,很多人會把 Queue(佇列) 和 Job(工作) 混為一談。但其實這兩者是不同的概念:
Queue 是一個「任務佇列」,你可以將需要花時間處理的任務先丟進去排隊,由背景程式(Worker)一件件處理。這樣做可以避免前端等待過久,提升整體使用者體驗。
Job 則是一個「任務的具體實作」 — — 也就是你定義好要做什麼事情的程式邏輯,像是:寄信、壓縮影片、匯出報表等。
這些 Job 實例可以被 dispatch(派送)到 queue 裡去等待背景執行。
在這個使用者對「等待」越來越沒耐心的時代,一個操作只要卡個三秒,可能就會讓使用者直接離開。
舉個例子:你打開 YouTube,結果轉圈圈等了三圈還沒開播,是不是很煩?
應用程式也一樣,有些操作像是發送 Email,處理第三方 API 回應等,就是「花時間」的動作。
為了讓整體流程順暢,我們會把這類操作包成 Job,丟進 queue 裡去背景處理,而不是在主流程中卡住使用者。
1️⃣ 建立 Job 類別:複製編輯php artisan make:job ProcessPodcast
Laravel 會產生一個位於 App\Jobs 的 Job 類別:
namespace App\Jobs;
use App\Models\Podcast;
use App\Services\AudioProcessor;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, SerializesModels;
public function __construct(
public Podcast $podcast,
) {}
public function handle(AudioProcessor $processor): void
{
// 實際執行的任務邏輯,例如處理 Podcast 音檔
$processor->process($this->podcast);
}
}
implements ShouldQueue 是關鍵:讓 Laravel 知道這是一個「應該要排入佇列處理」的 Job,而不是馬上執行。
ProcessPodcast::dispatch($podcast);
這行程式碼會將任務送進你指定的 queue 中等待背景執行。
你可以在 config/queue.php 中看到 queue 的預設設定:
'default' => env('QUEUE_CONNECTION', 'sync'),
Laravel 支援多種 queue「驅動(driver)」,例如:
'connections' => [
'sync' => [
'driver' => 'sync', // 同步,立即執行(不經過 queue)
],
'database' => [
'driver' => 'database',
'connection' => env('DB_QUEUE_CONNECTION'),
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => 'default',
'retry_after' => 90,
'block_for' => null,
],
],
若你選擇使用 database 或 redis,Job 被 dispatch 後會寫入對應資料庫或 Redis 的 queue 中,等待 Laravel Worker 去處理。
有兩個主要方法:
啟動 queue worker(推薦用於即時處理):php artisan queue:work
這會啟動一個常駐的 Worker,不斷地從 queue 中取出任務來執行。
用 Laravel Scheduler 配合 CronJob 執行排程任務:
Laravel 也支援「時間排程」任務,也就是 schedule:run 指令。這通常配合系統排程工具(如 Linux 的 cron)或 Kubernetes 的 CronJob 來執行。
在 K8S(Kubernetes)中設定 CronJob:
假設你部署在 K8S,可能會在 CronJob 設定檔中設置:
* * * * *
cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
這表示「每分鐘」都執行一次 Laravel 的排程指令,讓 Laravel 自動檢查有哪些 Job 要執行(例如 daily, everyFiveMinutes, everyMinute)。
* * * * *
│ │ │ │ │
│ │ │ │ └── 星期(0-6)
│ │ │ └──── 月份(1-12)
│ │ └────── 日期(1-31)
│ └──────── 小時(0-23)
└────────── 分鐘(0-59)
名稱代表意義Job要被執行的具體工作邏輯(例如寄信)Queue任務排隊等待區,放入多個 Job 排隊等候處理WorkerLaravel 背後真正處理任務的執行者CronJob系統/環境層級的定時任務排程工具